package com.jy.modules.cims.common.sysUtils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.TimeZone;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jy.modules.cims.common.CimsConstant;
import com.jy.modules.cims.common.exception.CimsExceptionConstant;

/**
 * @description FTP常用工具操作类。
 * @version v1.0
 * @author shengzhoutao
 * @Date 2015-8-20
 */
public class FTPClientImpl implements IFTPClient {
	private FTPClient ftpClient;

	private String hostname;// FTP服务器IP地址
	private int port;// FTP端口号
	private String user;// FTP用户
	private String password;// FTP密码

	private static Logger logger = LoggerFactory.getLogger(FTPClientImpl.class);

	/**
	 * @description 构造函数
	 */
	public FTPClientImpl() {

	}

	/**
	 * @description 构造函数
	 */
	public FTPClientImpl(String hostname, int port, String user, String Password) {
		this.init(hostname, port, user, Password);
	}

	/**
	 * @description 初始化参数
	 */
	public void init(String hostname, int port, String user, String Password) {
		this.hostname = hostname;
		this.port = port;
		this.user = user;
		this.password = Password;
		this.ftpClient = new FTPClient();
	}

	/**
	 * @description 判断是否登入成功
	 * @return 成功：true；false：失败
	 * */
	public boolean ftpLogin() {
		boolean isLogin = false;
		FTPClientConfig ftpClientConfig = new FTPClientConfig();
		ftpClientConfig.setServerTimeZoneId(TimeZone.getDefault().getID());
		this.ftpClient.setControlEncoding("GBK");
		this.ftpClient.configure(ftpClientConfig);
		try {
			if (this.port > 0) {
				this.ftpClient.connect(this.hostname, this.port);
			} else {
				this.ftpClient.connect(this.hostname);
			}
			// FTP服务器连接回答
			int reply = this.ftpClient.getReplyCode();
			if (!FTPReply.isPositiveCompletion(reply)) {
				this.ftpClient.disconnect();

				logger.info(CimsExceptionConstant.FTP_LOGIN_NOREPLY, this.user, this.hostname);

				return isLogin;
			}
			this.ftpClient.login(this.user, this.password);
			// 设置传输协议
			this.ftpClient.enterLocalPassiveMode();
			this.ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);

			logger.info(CimsExceptionConstant.FTP_LOGIN_SUCCESS, this.user, this.hostname);

			isLogin = true;
		} catch (Exception e) {
			e.printStackTrace();
			logger.info(CimsExceptionConstant.FTP_LOGIN_FAIL, this.user, this.hostname, e.getMessage());

		}
		this.ftpClient.setBufferSize(CimsConstant.FTP_BUFFER_SIZE);
		this.ftpClient.setDataTimeout(CimsConstant.FTP_DATA_TIMEOUT);

		return isLogin;
	}

	/**
	 * @description 退出关闭服务器链接
	 * */
	public void ftpLogOut() {
		if (null != this.ftpClient && this.ftpClient.isConnected()) {
			try {
				boolean reuslt = this.ftpClient.logout();// 退出FTP服务器
				if (reuslt) {
					logger.info(CimsExceptionConstant.FTP_LOGOUT_SUCCESS, this.user, this.hostname);
				}
			} catch (IOException e) {
				e.printStackTrace();
				logger.info(CimsExceptionConstant.FTP_LOGOUT_FAIL, this.user, this.hostname, e.getMessage());
			} finally {
				try {
					this.ftpClient.disconnect();// 关闭FTP服务器的连接
				} catch (IOException e) {
					e.printStackTrace();
					logger.info(CimsExceptionConstant.FTP_LOGOUT_FAIL, this.user, this.hostname, e.getMessage());
				}
			}
		}
	}

	/***
	 * @description 上传Ftp文件
	 * 
	 * @param localFile
	 *            当地文件
	 * @param romotUpLoadePath
	 *            上传服务器路径 应该以/结束
	 * */
	public boolean uploadFile(File localFile, String romotUpLoadePath) {

		BufferedInputStream inStream = null;
		boolean success = false;
		try {
			boolean makeDirectory = ftpClient.makeDirectory(romotUpLoadePath);// 上传文件夹不存在，需要创建文件夹
			logger.info("makeDirectory:" + makeDirectory);
			boolean changeWorkingDirectory = ftpClient.changeWorkingDirectory(romotUpLoadePath);// 改变工作路径
			logger.info("changeWorkingDirectory:" + changeWorkingDirectory);

			inStream = new BufferedInputStream(new FileInputStream(localFile));
			success = this.ftpClient.storeFile(localFile.getName(), inStream);
			if (success == true) {
				String oldFileName = localFile.getName();
				if (oldFileName.endsWith(".zip")) {
					String newFileName = oldFileName.replace(".zip", "_ok.zip");
					try {
						FTPFile[] ftpFile = ftpClient.listFiles(romotUpLoadePath + newFileName);
						if (ftpFile.length > 0) {
							ftpClient.deleteFile(romotUpLoadePath + newFileName);
						}

						ftpClient.rename(romotUpLoadePath + oldFileName, romotUpLoadePath + newFileName);
					} catch (Exception e) {
					}
				}
				return success;
			}

		} catch (FileNotFoundException e) {
			logger.error(CimsExceptionConstant.FTP_UPLOAD_FILE_FAIL, localFile.getName(), romotUpLoadePath, e.getMessage());
		} catch (IOException e) {
			logger.error(CimsExceptionConstant.FTP_UPLOAD_FILE_FAIL, localFile.getName(), romotUpLoadePath, e.getMessage());
		} finally {
			if (inStream != null) {
				try {
					inStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return success;
	}

	/***
	 * @description 下载文件
	 * 
	 * @param remoteFile
	 *            待下载文件名称(必要包含完整路径)
	 * @param localFile
	 *            下载到当地那个路径下(必要包含完整路径)
	 * */

	public boolean downloadFile(String remoteFile, String localFile) {
		BufferedOutputStream outStream = null;
		boolean success = false;
		try {
			outStream = new BufferedOutputStream(new FileOutputStream(localFile));

			success = this.ftpClient.retrieveFile(remoteFile, outStream);
			if (success == true) {
				return success;
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(CimsExceptionConstant.FTP_DOWNLOAD_FILE_FAIL, remoteFile, localFile, e.getMessage());
		} finally {
			if (null != outStream) {
				try {
					outStream.flush();
					outStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return success;
	}

	/***
	 * @description 下载文件到输出流
	 * @param remoteFile
	 *            待下载文件名称(必要包含完整路径)
	 * @param outputStream
	 *            文件输出流
	 * */

	public boolean downloadFile(String remoteFile, OutputStream outputStream) {
		boolean success = false;
		try {
			success = this.ftpClient.retrieveFile(remoteFile, outputStream);
			if (success == true) {
				return success;
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(CimsExceptionConstant.FTP_DOWNLOAD_OUTPUTSTREAM_FAIL, remoteFile, e.getMessage());
		} finally {
			if (null != outputStream) {
				try {
					outputStream.flush();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return success;
	}

	/***
	 * @description 上传文件夹
	 * @param localDirectory
	 *            当地文件夹
	 * @param remoteDirectoryPath
	 *            Ftp 服务器路径 以目录"/"结束
	 * */
	public boolean uploadDirectory(String localDirectory, String remoteDirectoryPath) {
		if (!localDirectory.endsWith(File.separator)) {
			localDirectory = localDirectory + File.separator;
		}
		if (!remoteDirectoryPath.endsWith(File.separator)) {
			remoteDirectoryPath = remoteDirectoryPath + File.separator;
		}

		File src = new File(localDirectory);
		try {
			remoteDirectoryPath = remoteDirectoryPath + src.getName() + File.separator;
			this.ftpClient.makeDirectory(remoteDirectoryPath);
			// ftpClient.listDirectories();
		} catch (IOException e) {
			e.printStackTrace();
			logger.error(CimsExceptionConstant.FTP_UPLOAD_DIR_FAIL, localDirectory, remoteDirectoryPath, e.getMessage());
		}
		File[] allFile = src.listFiles();
		if(null == allFile){
			return false;
		}
		for (int currentFile = 0; currentFile < allFile.length; currentFile++) {
			if (!allFile[currentFile].isDirectory()) {
				String srcName = allFile[currentFile].getPath().toString();
				uploadFile(new File(srcName), remoteDirectoryPath);
			}
		}
		for (int currentFile = 0; currentFile < allFile.length; currentFile++) {
			if (allFile[currentFile].isDirectory()) {
				// 递归
				uploadDirectory(allFile[currentFile].getPath().toString(), remoteDirectoryPath);
			}
		}
		return true;
	}

	/***
	 * @description 下载文件夹
	 * @param localDirectoryPath本地地址
	 * @param remoteDirectory
	 *            远程文件夹
	 * */
	public boolean downLoadDirectory(String localDirectoryPath, String remoteDirectory) {
		if (!localDirectoryPath.endsWith(File.separator)) {
			localDirectoryPath = localDirectoryPath + File.separator;
		}
		if (!remoteDirectory.endsWith(File.separator)) {
			remoteDirectory = remoteDirectory + File.separator;
		}

		try {
			String fileName = new File(remoteDirectory).getName();
			localDirectoryPath = localDirectoryPath + fileName + File.separator;
			new File(localDirectoryPath).mkdirs();
			FTPFile[] allFile = this.ftpClient.listFiles(remoteDirectory);
			for (int currentFile = 0; currentFile < allFile.length; currentFile++) {
				if (!allFile[currentFile].isDirectory()) {
					downloadFile(remoteDirectory + allFile[currentFile].getName(), localDirectoryPath);
				}
			}
			for (int currentFile = 0; currentFile < allFile.length; currentFile++) {
				if (allFile[currentFile].isDirectory()) {
					String strremoteDirectoryPath = remoteDirectory + allFile[currentFile].getName();
					downLoadDirectory(localDirectoryPath, strremoteDirectoryPath);
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
			logger.error(CimsExceptionConstant.FTP_DOWNLOAD_DIR_FAIL, remoteDirectory, localDirectoryPath, e.getMessage());
			return false;
		}
		return true;
	}

	/**
	 * @description 判断文件是否存在
	 * @param remoteFile
	 * @return
	 * @throws IOException
	 */
	public boolean existsFile(String remoteFile) throws IOException {
		FTPFile[] allFile = this.ftpClient.listFiles(remoteFile);
		if (allFile.length > 0) {
			return true;
		}
		return false;
	}

	// FtpClient的Set 和 Get 函数
	public FTPClient getFtpClient() {
		return ftpClient;
	}

	public void setFtpClient(FTPClient ftpClient) {
		this.ftpClient = ftpClient;
	}
}
